import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, MoreThan } from 'typeorm';
import {
  RestaurantMark,
  MarkType,
} from '../../entities/restaurant-mark.entity';
import { Restaurant } from '../../entities/restaurant.entity';
import { CreateMarkDto, QueryMarkDto } from './dto';
import {
  MarkStats,
  RestaurantMarkCheck,
} from '../../common/types/response.types';
import { PaginatedResponse } from '../../common/interfaces/api-response.interface';

@Injectable()
export class MarkService {
  constructor(
    @InjectRepository(RestaurantMark)
    private readonly markRepository: Repository<RestaurantMark>,
    @InjectRepository(Restaurant)
    private readonly restaurantRepository: Repository<Restaurant>,
  ) {}

  // 创建标记
  async createMark(createMarkDto: CreateMarkDto): Promise<RestaurantMark> {
    const { restaurantId, markType } = createMarkDto;

    // 验证餐厅是否存在
    const restaurant = await this.restaurantRepository.findOne({
      where: { id: restaurantId },
    });

    if (!restaurant) {
      throw new NotFoundException(`餐厅 ID ${restaurantId} 不存在`);
    }

    // 计算过期时间
    const now = new Date();
    let expiresAt: Date;

    if (markType === 'today') {
      // 今天标记：到今天23:59:59过期
      expiresAt = new Date(
        now.getFullYear(),
        now.getMonth(),
        now.getDate(),
        23,
        59,
        59,
      );
    } else {
      // 本周标记：到本周日23:59:59过期
      const daysUntilSunday = 7 - now.getDay();
      expiresAt = new Date(now);
      expiresAt.setDate(now.getDate() + daysUntilSunday);
      expiresAt.setHours(23, 59, 59, 999);
    }

    // 检查是否已存在相同类型的活跃标记
    const existingMark = await this.markRepository.findOne({
      where: {
        restaurant_id: restaurantId,
        mark_type: markType,
        expires_at: MoreThan(now),
      },
    });

    if (existingMark) {
      return existingMark;
    }

    // 创建新标记
    const mark = this.markRepository.create({
      restaurant_id: restaurantId,
      restaurant_name: restaurant.name,
      mark_type: markType,
      expires_at: expiresAt,
    });

    return this.markRepository.save(mark);
  }

  // 标记今天不想吃
  async markToday(restaurantId: string): Promise<RestaurantMark> {
    return this.createMark({ restaurantId, markType: 'today' });
  }

  // 标记本周不想吃
  async markWeek(restaurantId: string): Promise<RestaurantMark> {
    return this.createMark({ restaurantId, markType: 'week' });
  }

  // 获取所有标记
  async getAllMarks(
    query: QueryMarkDto,
  ): Promise<PaginatedResponse<RestaurantMark>> {
    const { page = 1, pageSize = 10 } = query;
    const skip = (page - 1) * pageSize;

    const [data, total] = await this.markRepository.findAndCount({
      order: { created_at: 'DESC' },
      skip,
      take: pageSize,
    });

    const totalPages = Math.ceil(total / pageSize);

    return {
      data,
      total,
      page,
      pageSize,
      totalPages,
    };
  }

  // 获取活跃标记
  async getActiveMarks(): Promise<RestaurantMark[]> {
    const now = new Date();
    return this.markRepository.find({
      where: {
        expires_at: MoreThan(now),
      },
      order: { created_at: 'DESC' },
    });
  }

  // 获取今天的标记
  async getTodayMarks(): Promise<RestaurantMark[]> {
    const now = new Date();
    return this.markRepository.find({
      where: {
        mark_type: 'today',
        expires_at: MoreThan(now),
      },
      order: { created_at: 'DESC' },
    });
  }

  // 获取本周的标记
  async getWeekMarks(): Promise<RestaurantMark[]> {
    const now = new Date();
    return this.markRepository.find({
      where: {
        mark_type: 'week',
        expires_at: MoreThan(now),
      },
      order: { created_at: 'DESC' },
    });
  }

  // 获取指定餐厅的标记
  async getRestaurantMarks(restaurantId: string): Promise<RestaurantMark[]> {
    const now = new Date();
    return this.markRepository.find({
      where: {
        restaurant_id: restaurantId,
        expires_at: MoreThan(now),
      },
      order: { created_at: 'DESC' },
    });
  }

  // 检查餐厅是否被标记
  async checkRestaurantMark(
    restaurantId: string,
    markType?: MarkType,
  ): Promise<RestaurantMarkCheck> {
    const now = new Date();
    const whereCondition: {
      restaurant_id: string;
      expires_at: any;
      mark_type?: MarkType;
    } = {
      restaurant_id: restaurantId,
      expires_at: MoreThan(now),
    };

    if (markType) {
      whereCondition.mark_type = markType;
    }

    const marks = await this.markRepository.find({
      where: whereCondition,
      order: { created_at: 'DESC' },
    });

    return {
      isMarked: marks.length > 0,
      marks,
    };
  }

  // 删除标记
  async deleteMark(id: string): Promise<void> {
    const mark = await this.markRepository.findOne({ where: { id } });
    if (!mark) {
      throw new NotFoundException(`标记 ID ${id} 不存在`);
    }
    await this.markRepository.remove(mark);
  }

  // 删除指定餐厅的标记
  async deleteRestaurantMarks(
    restaurantId: string,
    markType?: MarkType,
  ): Promise<void> {
    const whereCondition: { restaurant_id: string; mark_type?: MarkType } = {
      restaurant_id: restaurantId,
    };
    if (markType) {
      whereCondition.mark_type = markType;
    }
    await this.markRepository.delete(whereCondition);
  }

  // 删除特定类型的标记
  async deleteMarksByType(markType: MarkType): Promise<void> {
    await this.markRepository.delete({ mark_type: markType });
  }

  // 清空所有标记
  async clearAllMarks(): Promise<void> {
    await this.markRepository.clear();
  }

  // 清空过期标记
  async clearExpiredMarks(): Promise<void> {
    const now = new Date();
    await this.markRepository.delete({
      expires_at: MoreThan(now),
    });
  }

  // 获取标记统计
  async getMarkStats(): Promise<MarkStats> {
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const weekStart = new Date(today);
    weekStart.setDate(today.getDate() - today.getDay());

    const [totalMarks, todayMarks, weekMarks, activeMarks] = await Promise.all([
      this.markRepository.count(),
      this.markRepository.count({
        where: {
          created_at: MoreThan(today),
        },
      }),
      this.markRepository.count({
        where: {
          created_at: MoreThan(weekStart),
        },
      }),
      this.markRepository.count({
        where: {
          expires_at: MoreThan(now),
        },
      }),
    ]);

    return {
      totalMarks,
      todayMarks,
      weekMarks,
      activeMarks,
    };
  }
}
